package gw.com.android.ui.views;

import android.animation.Animator;
import android.animation.ValueAnimator;
import android.content.Context;
import android.support.annotation.Nullable;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;

import com.gwtsz.gts2.hx.R;

import java.util.ArrayList;
import java.util.List;
import java.util.ListIterator;
import java.util.Locale;

/**
 * 意见反馈中添加图片的控件
 *
 * @author jett
 * @since 2017-10-17.
 */
public class PickImageView extends LinearLayout {

    private static final int DEFAULT_MAX_COUNT = 3;

    private int itemCount = DEFAULT_MAX_COUNT;// 可添加的数量
    private List<PickedImageItem> items = new ArrayList<>();// 每张图片控件对应一个item
    private List<PickedImageItem> recycleItems = new ArrayList<>(); //回收利用item
    private boolean isAnim = false; // 动画期间，不能再次添加或删除
    private OnPickImageListener listener;

    private TextView tvImageCount;
    private FrameLayout cameraView;

    public PickImageView(Context context) {
        super(context);
        init();
    }

    public PickImageView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public PickImageView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    private void init() {
        installCameraView();
        setMinimumHeight(dp2px(109)); // 图片85 + 上下padding 24
    }

    public void setMaxCount(int max) {
        this.itemCount = max;
    }

    public int currentSelected() {
        return items.size();
    }

    /**
     * 添加一张图片
     *
     * @param path 图片地址
     */
    public void add(String path) {
        if (isAnim || items.size() >= itemCount) {
            return;
        }
        final PickedImageItem itemView = obtainItemView();
        itemView.setResource(path);
        initItemListener(itemView);

        int index = getChildCount() - 1;
        if (index < 0) index = 0;
        addView(itemView, index);
        items.add(itemView);
        notifyCameraViewText();
        if (items.size() >= itemCount) {
            hideCameraView(true);
        }

        addAnimation(itemView);
    }

    /**
     * 添加多张图片
     *
     * @param paths 图片地址
     */
    public void add(List<String> paths) {
        if (paths == null || paths.isEmpty()) {
            return;
        }
        if (isAnim || items.size() >= itemCount) {
            return;
        }
        List<PickedImageItem> addList = new ArrayList<>();
        for (String path : paths) {
            if (TextUtils.isEmpty(path)) {
                continue;
            }
            if (items.size() >= itemCount) {
                break;
            }
            final PickedImageItem itemView = obtainItemView();
            itemView.setResource(path);
            initItemListener(itemView);

            int index = getChildCount() - 1;
            if (index < 0) index = 0;
            addView(itemView, index);
            items.add(itemView);

            addList.add(itemView);
        }
        notifyCameraViewText();
        if (items.size() >= itemCount) {
            hideCameraView(true);
        }

        addAnimation(addList);
    }

    private void initItemListener(final PickedImageItem itemView) {
        itemView.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                if (listener != null) {
                    int position = items.indexOf(itemView);
                    listener.onPhoto(PickImageView.this, position);
                }
            }
        });
        itemView.setOnRemoveListener(new PickedImageItem.OnRemoveListener() {
            @Override
            public void onRemove(PickedImageItem item) {
                String resource = item.resource;
                remove(item);
                if (listener != null) {
                    listener.onRemove(PickImageView.this, item, resource);
                }
            }
        });
    }

    /**
     * 删除图片
     */
    private void remove(final PickedImageItem item) {
        if (isAnim || item == null) {
            return;
        }
        final List<PickedImageItem> animList = new ArrayList<>();
        int index = items.indexOf(item);
        if (index < items.size() - 1) {
            List<PickedImageItem> subList = items.subList(index + 1, items.size());
            animList.addAll(subList);
        }

        removeView(item);
        items.remove(item);
        recycle(item);
        notifyCameraViewText();
        showCameraView(true);

        removeAnimation(item, animList);
    }

    public void remove(List<String> paths) {
        if (paths == null) {
            return;
        }
        ListIterator<PickedImageItem> it = items.listIterator();
        while (it.hasNext()) {
            PickedImageItem item = it.next();
            if (paths.contains(item.resource)) {
                it.remove();
                removeView(item);
                recycle(item);
            }
        }
        notifyCameraViewText();
        showCameraView(false);
    }

    /**
     * 清空所有图片
     */
    public void clear() {
        if (!items.isEmpty()) {
            for (PickedImageItem item : items) {
                removeView(item);
                recycle(item);
            }
            items.clear();
            notifyCameraViewText();
            showCameraView(false);
        }
    }

    private void addAnimation(PickedImageItem view) {
        List<PickedImageItem> views = new ArrayList<>();
        views.add(view);
        addAnimation(views);
    }

    private void addAnimation(final List<PickedImageItem> views) {
        if (views == null || views.isEmpty()) {
            return;
        }
        final int width = views.get(0).getLayoutParams().width * views.size();
        ValueAnimator anim = ValueAnimator.ofFloat(0, 1.0F);
        anim.setDuration(200);
        anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                Float value = (Float) animation.getAnimatedValue();
                for (PickedImageItem view : views) {
                    view.setAlpha(value);
                }
                cameraView.setTranslationX((1 - value) * -width);
            }
        });
        anim.addListener(new MyAnimationListener());
        anim.start();
    }

    private void removeAnimation(final PickedImageItem item, final List<PickedImageItem> animList) {
        final int width = item.getLayoutParams().width;

        ValueAnimator anim = ValueAnimator.ofFloat(0, 1.0F);
        anim.setDuration(200);
        anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                Float value = (Float) animation.getAnimatedValue();

                float tranX = width * (1 - value);
                cameraView.setTranslationX(tranX);
                if (!animList.isEmpty()) {
                    for (PickedImageItem view : animList) {
                        view.setTranslationX(tranX);
                    }
                }
            }
        });
        anim.addListener(new MyAnimationListener());
        anim.start();
    }

    private void hideCameraView(boolean needAnim) {
        cameraView.setClickable(false);
        if (!needAnim) {
            cameraView.setAlpha(0);
            return;
        }
        ValueAnimator anim = ValueAnimator.ofFloat(0, 1.0F);
        anim.setDuration(200);
        anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                Float value = (Float) animation.getAnimatedValue();
                cameraView.setAlpha(1 - value);
            }
        });
        anim.start();

    }

    private void showCameraView(boolean needAnim) {
        cameraView.setClickable(true);
        if (!needAnim) {
            cameraView.setAlpha(1F);
            return;
        }
        ValueAnimator anim = ValueAnimator.ofFloat(0, 1.0F);
        anim.setDuration(200);
        anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                Float value = (Float) animation.getAnimatedValue();
                cameraView.setAlpha(value);
            }
        });
        anim.start();
    }

    private void notifyCameraViewText() {
        int size = items.size();
        if (size <= 0) {
            tvImageCount.setText(R.string.feedback_add_image);
        } else if (size >= itemCount) {
            tvImageCount.setText(String.format(Locale.getDefault(), "%d/%d", itemCount, itemCount));
        } else {
            tvImageCount.setText(String.format(Locale.getDefault(), "%d/%d", size, itemCount));
        }
    }

    private void recycle(PickedImageItem item) {
        item.reset();
        recycleItems.add(item);
    }

    private PickedImageItem obtainItemView() {
        if (!recycleItems.isEmpty()) {
            return recycleItems.remove(0);
        }
        PickedImageItem item = new PickedImageItem(getContext());
        LayoutParams param = new LayoutParams(dp2px(85), dp2px(85));
        param.rightMargin = dp2px(5);
        item.setLayoutParams(param);
        return item;
    }

    private View installCameraView() {
        cameraView = new FrameLayout(getContext());

        ImageView iv = new ImageView(getContext());
        iv.setScaleType(ImageView.ScaleType.FIT_XY);
        iv.setImageResource(R.mipmap.a_feedback_add);
        FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
        cameraView.addView(iv, params);

        tvImageCount = new TextView(getContext());
        tvImageCount.setTextColor(0xFFB5B5B5);
        tvImageCount.setTextSize(12);
        tvImageCount.setText(R.string.feedback_add_image);
        params = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
        params.gravity = Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL;
        params.bottomMargin = dp2px(15);
        cameraView.addView(tvImageCount, params);

        cameraView.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                if (listener != null) {
                    listener.onAdd(PickImageView.this);
                }
            }
        });

        LayoutParams mParam = new LayoutParams(dp2px(80), dp2px(80));
        mParam.gravity = Gravity.BOTTOM;
        addView(cameraView, mParam);

        return cameraView;
    }

    private class MyAnimationListener implements Animator.AnimatorListener {

        @Override
        public void onAnimationStart(Animator animation) {
            isAnim = true;
        }

        @Override
        public void onAnimationEnd(Animator animation) {
            isAnim = false;
        }

        @Override
        public void onAnimationCancel(Animator animation) {
            isAnim = false;
        }

        @Override
        public void onAnimationRepeat(Animator animation) {
        }
    }

    public void setOnPickImageListener(OnPickImageListener listener) {
        this.listener = listener;
    }

    public interface OnPickImageListener {
        void onAdd(PickImageView piv);

        void onRemove(PickImageView piv, PickedImageItem item, String resrouce);

        void onPhoto(PickImageView piv, int index);
    }

    private int dp2px(float dp) {
        DisplayMetrics metrics = getContext().getResources().getDisplayMetrics();
        return (int) (dp * (metrics.densityDpi / 160f) + 0.5F);
    }

}
